/**
 * 
 */
package com.thinkgsp.jxc.service.impl;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;

import org.apache.ibatis.session.RowBounds;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.thinkgsp.jxc.model.Customer;
import com.thinkgsp.jxc.model.CustomerState;
import com.thinkgsp.jxc.persistence.ContactBalanceMapper;
import com.thinkgsp.jxc.persistence.CustomerMapper;
import com.thinkgsp.jxc.persistence.RpContactMapper;
import com.thinkgsp.jxc.persistence.mybatis.PagingResult;
import com.thinkgsp.jxc.service.CustomerService;
import com.thinkgsp.jxc.service.ModelExistsException;
import com.thinkgsp.jxc.service.ServiceException;
import com.thinkgsp.sys.model.SysAccountPeriod;
import com.thinkgsp.sys.persistence.PersistenceException;

/**
 * 客户对象业务实现类
 * @author evan
 *
 */
@Service("customerService")
@Transactional
public class CustomerServiceImpl extends GeneralServiceImpl implements
		CustomerService {

	@Autowired
	private CustomerMapper custMapper;
	@Autowired
	private RpContactMapper contactMapper;
	@Autowired
	private ContactBalanceMapper cbMapper;
	
	public void setCustMapper(CustomerMapper custMapper) {
		this.custMapper = custMapper;
	}
	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getCust(java.lang.Integer)
	 */
	public Customer getCust(Integer custId) {
		return custMapper.getCust(custId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getCustByParent(java.lang.Integer)
	 */
	public List<Customer> getCustByParent(Integer parentId) {
		return custMapper.getCustByParent(parentId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getCustByEmp(java.lang.Integer)
	 */
	public List<Customer> getCustByEmp(Integer empId) {
		return custMapper.getCustByEmp(empId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getCustByDept(java.lang.Integer)
	 */
	public List<Customer> getCustByDept(Integer deptId) {
		return custMapper.getCustByDept(deptId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getCustByCode(java.lang.String)
	 */
	public Customer getCustByCode(String code) {
		return custMapper.getCustByCode(code);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#getAllCust(java.lang.Integer)
	 */
	public List<Customer> getAllCust(Integer custType) {
		return custMapper.getAllCust(custType);
	}
	
	public List<Customer> getDeletedCustomers() {
		return custMapper.getDeletedCustomers();
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#searchCust(java.lang.Integer, java.lang.String)
	 */
	public List<Customer> searchCust(Integer custType, String val) {
		return custMapper.searchCust(custType, val);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#saveCust(com.thinkgsp.jxc.model.Customer)
	 */
	public void saveCust(Customer cust) throws ModelExistsException,PersistenceException {
		try {
			if(cust.getCustomerId() == null || cust.getCustomerId() == 0) {
				//cust.setCreditAmount(0);
				//cust.setCreditDay(0);
				custMapper.insertCust(cust);
			} else {
				custMapper.updateCust(cust);
			}
		} catch(DuplicateKeyException e) {
			log.warn(e.getMessage());
			throw new ModelExistsException("客户:'" + cust.getCustomerName() + "' 已经存在。");
		} catch(Exception e) {
			log.error(e);
			throw new PersistenceException("客户:'" + cust.getCustomerName() + "' 保存失败。");
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#updateCustCreditAmount(java.lang.Integer, java.lang.Integer)
	 */
	public void updateCustCreditAmount(Integer custId, Integer amount) {
		custMapper.updateCustCreditAmount(custId, amount);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#updateCustCreditDay(java.lang.Integer, java.lang.Integer)
	 */
	public void updateCustCreditDay(Integer custId, Integer day) {
		custMapper.updateCustCreditDay(custId, day);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#lockCust(java.lang.Integer)
	 */
	public void lockCust(Integer custId) {
		custMapper.custLock(custId, true);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#unLockCust(java.lang.Integer)
	 */
	public void unLockCust(Integer custId) {
		custMapper.custLock(custId, false);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#expireCust(java.lang.Integer)
	 */
	public void expireCust(Integer custId) {
		custMapper.custExpire(custId, true);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#unExpireCust(java.lang.Integer)
	 */
	public void unExpireCust(Integer custId) {
		custMapper.custExpire(custId, false);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#enableCust(java.lang.Integer)
	 */
	@Deprecated
	public void enableCust(Integer custId) {
		custMapper.custEnable(custId, true);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#disableCust(java.lang.Integer)
	 */
	@Deprecated
	public void disableCust(Integer custId) {
		custMapper.custEnable(custId, false);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#deleteCust(java.lang.Integer)
	 */
	public void deleteCust(Integer custId) throws ServiceException {
		SysAccountPeriod period = periodMapper.getCurrentPeriod();
		Integer amount = custMapper.calcCustCreditAmount(custId, period.getFyear(), period.getPeriod());
		if(amount != null && amount > 0) {
			throw new ServiceException("该客户应收账款未结清，不能删除。");
		} else {
			custMapper.deleteCust(custId);
		}
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#restoreCust(java.lang.Integer)
	 */
	public void restoreCust(Integer custId) {
		custMapper.restoreCust(custId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#calcCustCreditAmount(java.lang.Integer, java.lang.Integer, java.lang.Integer)
	 */
	public Integer calcCustCreditAmount(Integer custId){
		SysAccountPeriod period = periodMapper.getCurrentPeriod();
		return custMapper.calcCustCreditAmount(custId, period.getFyear(), period.getPeriod());
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#calcCustCreditDay(java.lang.Integer)
	 */
	public Integer calcCustCreditDay(Integer custId) {
		return custMapper.calcCustCreditDay(custId);
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#checkStatus(java.lang.Integer, boolean)
	 */
	public boolean checkStatus(Integer custId, boolean throwException) throws ServiceException {
		Customer cust = custMapper.getCust(custId);
		Integer day = custMapper.calcCustCreditDay(custId);
		if(cust.getCreditDay() > 0 && day > cust.getCreditDay()) {
			//expireCust(custId);
			custMapper.custExpire(custId, true);
			cust.setAcctExpired(true);
		}
		if(cust.getAcctExpired()) {
			if(throwException) {
				throw new ServiceException("账户已过期。");
			} else {
				return false;
			}
		}
		if(cust.getAcctLocked()) {
			if(throwException) {
				throw new ServiceException("账户已锁定。");
			} else {
				return false;
			}
		}
		if(cust.getDeleted()) {
			if(throwException) {
				throw new ServiceException("账户已删除。");
			} else {
				return false;
			}
		}
		return true;
	}

	/* (non-Javadoc)
	 * @see com.thinkgsp.jxc.service.CustomerService#checkTradeCredit(java.lang.Integer, java.lang.Integer)
	 */
	public boolean checkTradeCredit(Integer custId, Integer amount) throws ServiceException {
		Customer cust = custMapper.getCust(custId);
		SysAccountPeriod period = periodMapper.getCurrentPeriod();
		Integer arpAmount = custMapper.calcCustCreditAmount(custId, period.getFyear(), period.getPeriod());
		if(cust.getCreditAmount().intValue() > 0 && (arpAmount + amount) > cust.getCreditAmount()) {
			throw new ServiceException("交易金额已经超出信用额度：信用额:" + cust.getCreditAmount() + ";应收金额:" + arpAmount + ";交易金额:" + amount);
		}
		return true;
	}

	public CustomerState checkCustomerState(Integer custId) {
		Customer cust = custMapper.getCust(custId);
		CustomerState cs = new CustomerState(cust);
		int debtDay = contactMapper.getCustomerDebtDay(custId);
		cs.setRemainDay(cs.getCreditDay().intValue() - debtDay);
		cs.setArpAmount(new BigDecimal(calcCustCreditAmount(custId)));
		if((cust.getCreditDay() > 0 && cs.getRemainDay() <= 0) || 
				(cust.getCreditAmount().intValue() > 0 && cs.getArpAmount().intValue() >= cust.getCreditAmount().intValue())) {
			expireCust(custId);
		} else {
			if(cust.getAcctExpired()) {
				unExpireCust(custId);
			}
		}
		return cs;
	}
	public PagingResult<Customer> getCustByEmp(Integer empId, int start,
			int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("empId", empId);
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.CustomerMapper.getCustByEmpCount", 
				"com.thinkgsp.jxc.persistence.CustomerMapper.getCustByEmpPaging", map, rows);
	}
	public PagingResult<Customer> getCustByDept(Integer deptId, int start,
			int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("deptId", deptId);
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.CustomerMapper.getCustByDeptCount", 
				"com.thinkgsp.jxc.persistence.CustomerMapper.getCustByDeptPaging", map, rows);
	}
	public PagingResult<Customer> getAllCust(Integer custType, int start,
			int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("custType", custType);
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.CustomerMapper.getAllCustCount", 
				"com.thinkgsp.jxc.persistence.CustomerMapper.getAllCustPaging", map, rows);
	}
	public PagingResult<Customer> getDeletedCustomers(int start, int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.CustomerMapper.getDeletedCustomerCount", 
				"com.thinkgsp.jxc.persistence.CustomerMapper.getDeletedCustomersPaging", map, rows);
	}
	public PagingResult<Customer> searchCust(Integer custType, String val,
			int start, int size) {
		HashMap<String, Object> map = new HashMap<String, Object>();
		map.put("custType", custType);
		map.put("val", val);
		RowBounds rows = new RowBounds(start,size);
		return queryPagingHandler.queryPagingResult(
				"com.thinkgsp.jxc.persistence.CustomerMapper.searchCustCount", 
				"com.thinkgsp.jxc.persistence.CustomerMapper.searchCustPaging", map, rows);
	}
}
